class LRUCache {
private:
	unordered_map<int, list<pair<int, int>>::iterator> _hashMap; // hash能做到查找get更新是O(1)
	list<pair<int, int>> _LRUList; // 假设尾部数据就是最近少用的,最近使用的放在头部
	size_t _capacity; // 标记容量,满了就弹出链表尾的元素+在哈希表删除该元素的键值对

public:
    LRUCache(int capacity)
        : _capacity(capacity)
    {}
    
    int get(int key) 
    {
        //_hashMap中的key: key value：list的迭代器(LtIter)
        auto ret = _hashMap.find(key);//先查找是否在哈希表中
        if(ret != _hashMap.end()) // 存在
        {
            // 更新当前元素到链表头部
            auto it= ret->second; // 该元素在list中的位置
            // 把元素转移到链表头部,相当于头插,但是这这里不用更新迭代器,因为迭代器里面存的还是这个节点的指针
            _LRUList.splice(_LRUList.begin(), _LRUList, it);
            //it:是链表的迭代器,调用operator->,返回数据的地址,list中的数据是pair,所以返回的是pair*
            //pair<int,int>  我们要的是第二个成员的值,本来应该是it->->second 但是省略了一个箭头 
            return it->second; // 返回key对应的value 
        }
        else // 该元素不存在
        {
            return -1;
        }
    }
    
    void put(int key, int value)
    {
        auto ret = _hashMap.find(key);
        if(ret == _hashMap.end()) // 不存在->新增
        {
            //判断容量的时候,最好不要使用求list的大小来判断,因为C++中,这个方法可能不是O(1)
            //if(_capacity == _LRUList.size()) 不建议
            if(_capacity == _hashMap.size()) // 容量满了
            {
                pair<int, int> back = _LRUList.back(); // 取出链表尾部的数据
                //在哈希表中删除该数据 + 在链表弹出该元素
                _hashMap.erase(back.first);//back.first是key
                _LRUList.pop_back();
            }
            //头插入当前元素 + 哈希表新增键值对{key-该元素在list的位置(链表头部)}
            _LRUList.push_front(make_pair(key, value));
            _hashMap[key] = _LRUList.begin();
        }
        else
        {
            // 修改节点的值 + 当前数据放到链表头部
            auto it = ret->second; // it是list的迭代器
            it->second = value; // 更新节点的值
            _LRUList.splice(_LRUList.begin(),_LRUList,it); // 把当前节点转移到头部
        }
    }
};

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */